package com.zzxz.practicaltrainingsys.component;

import com.alibaba.fastjson.JSON;
import com.zzxz.practicaltrainingsys.entity.ChatRecord;
import com.zzxz.practicaltrainingsys.entity.Message;
import com.zzxz.practicaltrainingsys.entity.UserList;
import com.zzxz.practicaltrainingsys.service.ChatRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/socket/{chatType}/{inviteCode}/{username}")
public class WebSocketServer {

    public static final Map<String, Session> publicSessions = new ConcurrentHashMap<>();
    public static final Map<String, Map<String, Session>> groupSessions = new ConcurrentHashMap<>();

    private static ChatRecordService chatRecordService;

    @Autowired
    public void setChatRecordService(ChatRecordService chatRecordService) {
        WebSocketServer.chatRecordService = chatRecordService;
    }

    @OnOpen
    public void onOpen(Session session,
                       @PathParam("chatType") String chatType,
                       @PathParam("inviteCode") String inviteCode,
                       @PathParam("username") String username) {

        if ("public".equals(chatType)) {
            if (!publicSessions.containsKey(username)) {
                publicSessions.put(username, session);
                sendAllPublicMessage(setUserList(publicSessions));
                showUserList(publicSessions, "公共聊天室");

                // 发送历史聊天记录给新用户
                sendHistoryMessages(session, chatType, inviteCode);
            }
        } else if ("group".equals(chatType)) {
            Map<String, Session> group = groupSessions.computeIfAbsent(inviteCode, k -> new ConcurrentHashMap<>());
            if (!group.containsKey(username)) {
                group.put(username, session);
                sendAllGroupMessage(inviteCode, setUserList(group));
                showUserList(group, "分组聊天室：" + inviteCode);

                // 发送历史聊天记录给新用户
                sendHistoryMessages(session, chatType, inviteCode);
            }
        }
    }

    @OnClose
    public void onClose(@PathParam("chatType") String chatType,
                        @PathParam("inviteCode") String inviteCode,
                        @PathParam("username") String username) {

        if ("public".equals(chatType)) {
            if (username != null && publicSessions.containsKey(username)) {
                publicSessions.remove(username);
                sendAllPublicMessage(setUserList(publicSessions));
                showUserList(publicSessions, "公共聊天室");
            }
        } else if ("group".equals(chatType)) {
            Map<String, Session> group = groupSessions.get(inviteCode);
            if (group != null && username != null && group.containsKey(username)) {
                group.remove(username);
                sendAllGroupMessage(inviteCode, setUserList(group));
                showUserList(group, "分组聊天室：" + inviteCode);
            }
        }
    }

    @OnMessage
    public void onMessage(String message,
                          @PathParam("chatType") String chatType,
                          @PathParam("inviteCode") String inviteCode) {

        Message msg = JSON.parseObject(message, Message.class);
        msg.setType("chatmsg");

        // 保存聊天记录到数据库
        if (chatRecordService != null) {
            chatRecordService.saveChatRecord(msg, chatType, inviteCode);
        }

        String msgJson = JSON.toJSONString(msg);

        if ("public".equals(chatType)) {
            sendAllPublicMessage(msgJson);
        } else if ("group".equals(chatType)) {
            sendAllGroupMessage(inviteCode, msgJson);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 发送历史聊天记录给新用户
     */
    private void sendHistoryMessages(Session session, String chatType, String inviteCode) {
        if (chatRecordService == null) {
            return;
        }

        try {
            // 获取最近20条聊天记录
            List<ChatRecord> historyRecords = chatRecordService.getRecentChatRecords(chatType, inviteCode, 20);

            for (ChatRecord record : historyRecords) {
                Message historyMsg = new Message();
                historyMsg.setFrom(record.getUsername());
                historyMsg.setContent(record.getContent());
                historyMsg.setTime(record.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                historyMsg.setType("chatmsg");

                // 设置用户信息
                if (record.getRealName() != null || record.getUserType() != null) {
                    Message.UserInfo userInfo = new Message.UserInfo();
                    userInfo.setRealName(record.getRealName());
                    userInfo.setType(record.getUserType());
                    historyMsg.setUserInfo(userInfo);
                }

                String historyMsgJson = JSON.toJSONString(historyMsg);
                session.getBasicRemote().sendText(historyMsgJson);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void showUserList(Map<String, Session> map, String chatRoomName) {
        System.out.println("------ " + chatRoomName + " 当前在线用户 ------");
        for (String username : map.keySet()) {
            System.out.println(username);
        }
        System.out.println("-------------------------------------");
    }

    private String setUserList(Map<String, Session> map) {
        ArrayList<String> list = new ArrayList<>(map.keySet());
        UserList userList = new UserList();
        userList.setUserlist(list);
        userList.setType("userlist");
        return JSON.toJSONString(userList);
    }

    private void sendAllPublicMessage(String message) {
        try {
            for (Session session : publicSessions.values()) {
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendAllGroupMessage(String inviteCode, String message) {
        try {
            Map<String, Session> group = groupSessions.get(inviteCode);
            if (group != null) {
                for (Session session : group.values()) {
                    session.getBasicRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}